let _Vue = null
export default class VueRouter {
  static install (Vue) {
    //  1、判断当前插件是否已经被安装，即是否已经执行install方法
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    //  2、把Vue构造函数记录到全局变量
    _Vue = Vue
    //  3、把创建Vue实例时传入的router对象注入到Vue实例上，这里需要使用Vue的混入方法
    _Vue.mixin({
      beforeCreate () {
        //  加上这个判断是为了防止$router被挂载多次，因为在组件中也会执行这个方法，但是只有vue实例的$options上才有router属性，
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }

  //  构造函数中需要初始化三个属性：options、routeMap、data
  constructor (options) {
    this.options = options
    this.routeMap = {}
    //  设置data时，需要调用vue的observable方法，用于创建一个响应对象
    this.data = _Vue.observable({
      current: '/'
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents(_Vue)
    this.initEvent()
  }

  createRouteMap () {
    //  遍历options中的routes规则，把路由规则解析成键值对，存放到routeMap中
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

  initComponents (Vue) {
    _Vue.component('router-link', {
      props: {
        to: String
      },
      render (h) {
        return h('a', {
          attrs: {
            href: '#' + this.to
          },
          on: {
            click: this.clickHanlder
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHanlder (e) {
          window.location.hash = '#' + this.to
          this.$router.data.current = this.to
          e.preventDefault()
        }
      }
    })

    const _self = this
    _Vue.component('router-view', {
      render (h) {
        const component = _self.routeMap[_self.data.current] || _self.routeMap['*']
        return h(component)
      }
    })
  }

  initEvent () {
    window.addEventListener('load', this.hashChange.bind(this))
    window.addEventListener('hashchange', this.hashChange.bind(this))
  }

  hashChange () {
    if (!window.location.hash) {
      window.location.hash = '#/'
    }
    this.data.current = window.location.hash.substr(1)
  }
}
